/*
 *                  BioJava development code
 *
 * This code may be freely distributed and modified under the
 * terms of the GNU Lesser General Public Licence.  This should
 * be distributed with the code.  If you do not have a copy,
 * see:
 *
 *      http://www.gnu.org/copyleft/lesser.html
 *
 * Copyright for this code is held jointly by the individual
 * authors.  These should be listed in @author doc comments.
 *
 * For more information on the BioJava project and its aims,
 * or to join the biojava-l mailing list, visit the home page
 * at:
 *
 *      http://www.biojava.org/
 * 
 * Created on Jun 26, 2007
 * 
 */

package org.biojava.services.das.servlets;

import java.awt.Image;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.biojava.services.das.dao.ProjectBean;
import org.biojava.services.das.dao.RegistryUser;
import org.biojava.services.das.registry.UserManager;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class FileUploadServlet extends HttpServlet {

	public static final int MAX_REQ_SIZE = 100000;
	public static final String TMP_DIR = "/tmp/";
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public static final String LOGIN = "login.jsp";
	public static final String UPLOAD_ACTION = "registerProjectAction.jsp";
	public static final String UPLOAD_FORM = "registerProject.jsp";
	public static final int IMAGE_HEIGHT = 16;
	public static final String DEFAULT_IMAGE_FORMAT = "jpg";

	public FileUploadServlet() {

	}

	public void init() throws ServletException {
		// TODO Auto-generated method stub
		super.init();
	}

	public void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {

		HttpSession session=req.getSession(true);
//		SessionCached session = new SessionCached(null);
//		Cookie cookies[] = req.getCookies();
//		for (Cookie cookie : cookies) {
//			if (cookie.getName().equals("JSESSIONID")) {
//				session.setId(cookie.getValue());
//			}
//		}

		String email = (String) session.getAttribute("email");
		if (email == null) {
			(req.getRequestDispatcher(LOGIN)).forward(req, resp);
			return;
		}

		(req.getRequestDispatcher(UPLOAD_FORM)).forward(req, resp);
	}

	public void doPost(HttpServletRequest req, HttpServletResponse res)
			throws ServletException, IOException {

		HttpSession session = req.getSession(true);
		String email = (String) session.getAttribute("email");
		if (email == null) {
			(req.getRequestDispatcher(LOGIN)).forward(req, res);
			return;
		}

		// System.out.println("do file upload checks ");
		// only works if logged in...

		boolean isMultipart = ServletFileUpload.isMultipartContent(req);

		if (!isMultipart) {
			String message = "you did not upload an icon";
			req.setAttribute("message", message);
			req.getRequestDispatcher(UPLOAD_FORM).forward(req, res);
			return;
		}

		// Create a factory for disk-based file items
		DiskFileItemFactory factory = new DiskFileItemFactory();

		// Set factory constraints
		factory.setSizeThreshold(200);
		factory.setRepository(new File(TMP_DIR));

		// Create a new file upload handler
		ServletFileUpload upload = new ServletFileUpload(factory);

		// Set overall request size constraint
		upload.setSizeMax(MAX_REQ_SIZE);

		// Parse the request

		List items = new ArrayList();
		try {

			items = upload.parseRequest(req);

		} catch (Exception e) {
			String message = e.getMessage();
			// System.out.println(message);
			req.setAttribute("message", message);
			req.getRequestDispatcher(UPLOAD_FORM).forward(req, res);
			return;
		}

		// get the user data...
		BeanFactory ctex=(new ClassPathXmlApplicationContext("SpringDAO.xml"));
  		UserManager manager = (UserManager)ctex.getBean("userManager");
		
		RegistryUser user = manager.getUser(email);

		if (user == null) {
			String message = "could not identify user " + email;
			req.setAttribute("message", message);
			req.getRequestDispatcher(LOGIN).forward(req, res);
			return;
		}

		// Process the uploaded items

		Iterator iter = items.iterator();

		while (iter.hasNext()) {
			FileItem item = (FileItem) iter.next();

			if (item.isFormField()) {
				String name = item.getFieldName();
				String value = item.getString();

				req.setAttribute(name, value);
			}
		}

		iter = items.iterator();

		ProjectBean project = new ProjectBean();
		DiskFileItem ditem = null;

		while (iter.hasNext()) {
			FileItem item = (FileItem) iter.next();

			if (item.isFormField()) {

				String name = item.getFieldName();
				String value = item.getString();
				// System.out.println(name + " >" + value+"<");
				if (name.equals("projectName")) {
					if (value.equals("")) {
						String message = "you did not provide a name for the project.";
						req.setAttribute("message", message);
						req.getRequestDispatcher(UPLOAD_FORM).forward(req, res);
						return;

					}
					project.setName(value);
				}
				if (name.equals("projectUrl")) {
					URL homepage = null;

					try {
						homepage = new URL(value);
					} catch (MalformedURLException e) {
						String message = "you did not provide a valid URL"
								+ " for the homepage of the project.";
						req.setAttribute("message", message);
						req.getRequestDispatcher(UPLOAD_FORM).forward(req, res);
						return;
					}
					project.setHomepage(homepage);

				}
				if (name.equals("projectDesc")) {
					project.setDescription(value);
				}
				if (name.equals("projectOwner")) {

					project.setOwner(user);
				}

			} else {
				if (!item.isFormField()) {

					String fieldName = item.getFieldName();
					String fileName = item.getName();
					String contentType = item.getContentType();
					boolean isInMemory = item.isInMemory();
					long sizeInBytes = item.getSize();
					if (fileName.equals("")) {
						String message = "please provide an icon for the project.";
						req.setAttribute("message", message);
						req.getRequestDispatcher(UPLOAD_FORM).forward(req, res);
						return;
					}
					// if filename is .ico this format is not supported
					if (fileName.endsWith(".ico")) {
						String message = "The icon format .ico is not supported please provide an alternative format for the icon for the project.";
						req.setAttribute("message", message);
						req.getRequestDispatcher(UPLOAD_FORM).forward(req, res);
						return;
					}
					System.out.println(fieldName + " >" + fileName + "< "
							+ contentType + " " + isInMemory + " "
							+ sizeInBytes);

					if (item instanceof DiskFileItem) {
						ditem = (DiskFileItem) item;

					}

				}
			}
		}

		manager.createProject(project, user.getUserID());
		if (ditem != null) {
			try {

				scaleAndStoreImage(manager, ditem, project);
			} catch (Exception e) {
				e.printStackTrace();
				String message = e.getMessage();
				req.setAttribute("message", message);
				req.getRequestDispatcher(UPLOAD_FORM).forward(req, res);
				return;
			}
		} else
			System.out.println("did not find image in file system!");
		req.setAttribute("projectID", project.getProjectID() + "");
		(req.getRequestDispatcher(UPLOAD_ACTION)).forward(req, res);
		return;
	}

	private void scaleAndStoreImage(UserManager manager, DiskFileItem item,
			ProjectBean p) throws IOException {
		// System.out.println("a disk file item!");

		Image image = ImageIO.read(item.getInputStream());

		item.delete();

		if (image == null) {
			manager.deleteProject(p);
			throw new IOException(
					"problem when reading image, is it an image? ");
		}

		Image newImage = ImageUtil.scaleImage(IMAGE_HEIGHT, image);

		manager.writeProjectImage(p, newImage, DEFAULT_IMAGE_FORMAT);

	}

}
